<template>
	<view class="content">
		<view id="viewport" @click="three.ray" :prop="renderJsData" :change:prop="three.create" />
	</view>
</template>

<script>
	export default {
		data() {
			return {
				domId: ''
			}
		},
		mounted() {
			this.domId = 'viewport';
		},
		computed: {
			// renderJs所需数据都通过该计算属性传递
			renderJsData() {
				return {
					domId: this.domId
				}
			}
		},
		methods: {
			clickItem(el) {
				uni.showToast({
					title: '点击到一个元素',
					icon: 'none'
				})
			}
		}
	}
</script>

<script module="three" lang="renderjs">
	import conifg from './config.js';
	import * as THREE from 'three';
	import * as utils from '@/utils/index.js';
	let OrbitControls = require('three-orbit-controls')(THREE);
	THREE.OrbitControls = OrbitControls;

	export default {
		data() {
			return {
				scene: null,
				camera: null,
				renderer: null,
				controls: null,
				canvas: null,
				elements: [],
				pageConfig: JSON.parse(JSON.stringify(conifg)),
				isInit: false
			}
		},
		methods: {
			// 初始化
			async create() {
				this.$nextTick(()=>{
					//避免重复初始化
					if (this.isInit) {
						return;
					}
					this.isInit = true;
					
					let {
						domId
					} = this.renderJsData;
					
					let scene, camera, renderer, controls;
					let viewport = document.getElementById(domId);
					
					let {
						offsetWidth: width,
						offsetHeight: height
					} = viewport;
					
					//场景
					scene = new THREE.Scene();
					//摄像机
					camera = new THREE.PerspectiveCamera(90, width / height, 0.1, 100);
					camera.position.set(0, 0, 0.01);
					//渲染器
					renderer = new THREE.WebGLRenderer();
					renderer.setSize(width, height);
					viewport.appendChild(renderer.domElement);
					//镜头控制器
					controls = new THREE.OrbitControls(camera, renderer.domElement);
					
					this.camera = camera;
					this.scene = scene;
					this.renderer = renderer;
					this.controls = controls;
					this.canvas = renderer.domElement;
					
					this.initSkyBox();
					this.updateView();
					this.initHotPoints();
				})

				
			},
			// 初始化天空盒
			initSkyBox() {
				let {
					skyboxPath,
					skyboxImages
				} = this.pageConfig;
				console.log('pageConfig:', this.pageConfig);
				utils.cubeTextureLoader(skyboxPath, skyboxImages).then(res => {
					this.scene.background = res;
					console.log()
				})
			},
			// 射线检测
			ray(e) {
				let {
					canvas,
					camera,
					scene
				} = this.$data;

				let {
					clientX,
					clientY
				} = e.changedTouches[0];

				// 坐标归一化
				clientY += (canvas.getBoundingClientRect().top / 2);
				let x = (clientX / window.innerWidth) * 2 - 1;
				let y = -(clientY / window.innerHeight) * 2 + 1

				let vector3 = new THREE.Vector3(x, y, 1);
				let worldVector = vector3.unproject(camera);
				let ray = worldVector.sub(camera.position).normalize();

				// 判断当前是否选中物体
				let element = utils.getIntersects(x, y, this.elements, this.camera, this.scene);

				if (element) {
					this.$ownerInstance.callMethod('clickItem', element);
				}
			},
			// 初始化热点
			initHotPoints() {
				if (this.pageConfig.hotPoints.length > 0) {
					this.pageConfig.hotPoints.forEach((item, i) => {
						let pos = new THREE.Vector3(item.position.x, item.position.y, item.position.z);
						let scale = new THREE.Vector3(item.scale.x, item.scale.y, item.scale.z);
						let sprite = utils.createSprite(item.imageSrc, pos, scale);
						sprite.name = 'hotpoint_' + i++;
						this.scene.add(sprite);
						this.elements.push(sprite);
					})
				}
			},
			updateView() {
				let {
					renderer,
					scene,
					camera
				} = this.$data;
				requestAnimationFrame(this.updateView);
				renderer.render(scene, camera);
			}
		}
	}
</script>

<style>
	#viewport {
		position: absolute;
		left: 0;
		top: 0;
		width: 100%;
		height: 100%;
	}
</style>
